package cn.ilikes.tools.hbase.jpa;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.ProviderUtil;

import org.slf4j.Logger;

import cn.ilikes.tools.hbase.jpa.configs.Configure;
import cn.ilikes.tools.hbase.jpa.configs.JPAHBaseConfigurationException;
import cn.ilikes.tools.hbase.jpa.persistences.DefaultJPAHBaseEntityManagerFactory;
import cn.ilikes.tools.hbase.jpa.schemas.HBaseSchemaManager;
import cn.ilikes.tools.hbase.jpa.schemas.JPAHBaseSchemaException;
import cn.ilikes.tools.hbase.jpa.schemas.SchemaManager;
import cn.ilikes.tools.logs.Loggerfactory;

/**
 * JPA HBase Persistence Provider
 * 
 * @author fack
 * 
 */
public class JPAHbasePersistenceProvider implements PersistenceProvider {

	private static Logger logger = Loggerfactory.instance(JPAHbasePersistenceProvider.class);

	/**
	 * key : persistenceUnitsName value: EntityManagerFactory
	 */
	private static Map<String, DefaultJPAHBaseEntityManagerFactory> entityManagerFactoryMap = new HashMap<String, DefaultJPAHBaseEntityManagerFactory>();

	public JPAHbasePersistenceProvider() {
		super();
		jpaHbaseinit();
	}

	private void jpaHbaseinit() {
		JPAHbaseSystemEnv.getHbaseSystemEnv().initSystemEnv();
	}

	/**
	 * persistenceUnitsName ; Map
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public EntityManagerFactory createEntityManagerFactory(String persistenceUnitsName, Map persistenceUnitsConfig) {
		Loggerfactory.info(logger, " create entity manager  factory  persistence units  name : " + persistenceUnitsName);
		DefaultJPAHBaseEntityManagerFactory entityManagerFactory = entityManagerFactoryMap.get(persistenceUnitsName);
		if (entityManagerFactory == null) {
			synchronized (entityManagerFactoryMap) {
				try {
					Properties persistenceUnitsProperties = new Properties();
					if (persistenceUnitsConfig == null)
						persistenceUnitsConfig = new HashMap();
					persistenceUnitsProperties.putAll(persistenceUnitsConfig);
					//init
					JPAHbasePersistenUnitEnv hbasePersistenUnitEnv = initHbasePersistenceUnitEnv(persistenceUnitsName, persistenceUnitsProperties);
					//init SchemaManager
					SchemaManager schemaManager = new HBaseSchemaManager(hbasePersistenUnitEnv);
					schemaManager.execSchema(schemaManager.getExecType());
					//end
					entityManagerFactory = new DefaultJPAHBaseEntityManagerFactory(persistenceUnitsProperties, hbasePersistenUnitEnv);

					entityManagerFactoryMap.put(persistenceUnitsName, entityManagerFactory);
				} catch (JPAHBaseSchemaException e) {
					Loggerfactory.error(logger, "create default  JPA  HBase  EntityManager  Factory  not  success  ", e);
				}
			}
		}
		return entityManagerFactory;
	}

	@Override
	public ProviderUtil getProviderUtil() {
		throw new JPAHBaseNoSupportException("this not work ");
	}

	/**
	 * 初始化 persistence Units Name 指定的 entity manager factory
	 * 
	 * createEntityManagerFactory(String persistenceUnitsName, Map
	 * configs)
	 * 
	 * @param persistencefile
	 * @param configs
	 *                  -> configs
	 */
	private JPAHbasePersistenUnitEnv initHbasePersistenceUnitEnv(String persistenceUnitsName, Properties configs) {

		Loggerfactory.info(logger, " persistenceUnitsName " + persistenceUnitsName + "'s  entity manager  factory  start  init");
		try {
			JPAHbasePersistenUnitEnv hbasePersistenUnitEnv = new JPAHbasePersistenUnitEnv(persistenceUnitsName, JPAHbaseSystemEnv.getHbaseSystemEnv());
			//解析persistence file 。得到 persistenceUnitsName 相关信息，并load 到 JPA HBase system env .
			Configure configure = new Configure(configs);

			configure.config(persistenceUnitsName, hbasePersistenUnitEnv);

			return hbasePersistenUnitEnv;
		} catch (JPAHBaseConfigurationException e) {
			Loggerfactory.error(logger, e);
			throw new JPAHBaseRuntimeException(e);
		}

	}

	@Override
	public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo arg0, Map arg1) {
		throw new JPAHBaseNoSupportException("this not work ");
	}

	public static JPAHbasePersistenUnitEnv findJPAHbasePersistenUnitEnv(String puName) {

		return entityManagerFactoryMap.get(puName).getHbasePersistenUnitEnv();
	}

}
